<?php
	// Classe définissant un accès singleton a une base de donnees
	// Auteur : Sebastian Mosser

final class Database implements iDatabase, iSingleton {

	private static $_myDatabase;
	private $_server;
	private $_user;
	private $_password;
	private $_dbName;
	private static $VOID_QUERY = "SELECT TRUE;";
	
	
	protected function __construct() {
		/**
		$this->_server   = "localhost";
		$this->_user     = "phpBalloon";
		$this->_password = "zxcvfghdflk:3564";
		$this->_dbName   = "balloon";
		**/
		$this->_server   = BALLOON_DB_SERVER;
		$this->_user     = BALLOON_DB_USER;
		$this->_password = BALLOON_DB_PASSWD;
		$this->_dbName   = BALLOON_DB_NAME;
		
	}
	
	// Pour obtenir le singleton d'accès a la base de données
	public static function getSingleton() {
		if (! isset(self::$_myDatabase))
			self::$_myDatabase = new Database();
			
		return self::$_myDatabase;
	}
	
   private function throwExc($pb) {
      throw new DatabaseException($pb);
   }	
	
	// Execute une requete 
	public function execute($query,$esc = False) {
		// Etape 1 : connection
		@mysql_connect($this->_server, $this->_user, $this->_password)
   		or $this->throwExc("Unable to connect to database !");

   	// Etape 2 : choix du schéma de base
   	@mysql_select_db($this->_dbName) 
   	   or $this->throwExc("Unable to select Balloon Database");

   	// Etape 3 : Echappement des injections SQL
   	if ($esc)
   		$query = mysql_real_escape_string($query);

   	// Etape 4 : Execution de la requete
   	$dbAnswer = mysql_query($query);

   	// Etape 5 : test de la validité :
   	if (! $dbAnswer)
   		throw new DatabaseException($query);
   	// Etape 6 : renvoi du jeu de résultats :
   	return $dbAnswer;
	}
	
	
	// Execute une instertion et renvoi l'autoincrement
	// Renvoi un tablau a 2 eléments : [id,dbAnswer]
	public function executeInsert($query) { 
			// Etape 1 : connection
		@mysql_connect($this->_server, $this->_user, $this->_password)
   		or $this->throwExc("Unable to connect to database !");

   	// Etape 2 : choix du schéma de base
   	@mysql_select_db($this->_dbName) 
   	   or $this->throwExc("Unable to select Balloon Database");

   	// Etape 3 : Execution de la requete
   	$dbAnswer = mysql_query($query);

   	// Etape 4 : test de la validité :
   	if (! $dbAnswer)
   		throw new DatabaseException($query);
   	// Etape 5 : renvoi du jeu de résultats :
   	$id = $this->lastKeyValue();
   	$result = array();
   	$result[0] = $id;
   	$result[1] = $dbAnswer;
   	
   	return $result;
	}
	
	// Recupère la valeur de la dernière auto-incrementation effectuée
	private function lastKeyValue() {
		return mysql_insert_id();
	}
	
	// Prevention des injections SQL
	public static function escape($string) {
		$myDb = self::getSingleton();
		$myDb->execute(self::$VOID_QUERY);
		return mysql_real_escape_string($string);
	}
	
	// Association d'un jeu de resultat dans un tableau
	public static function assoc($resultSet) {
		return mysql_fetch_assoc($resultSet);
	}
	
	
	/** TODO : gerer de manière logicielle les import/export pour ne plus
	 * dépendre d'un système Unices
	 */

	// Accès aux binaires MySQL :
	private static $Dumper = BALLOON_DB_DUMPER;
	private static $MySql = BALLOON_DB_EXE;

  // Permet l'exportation d'une base de données :
  public static function export() {
  	
  	$currentDb = Database::getSingleton();
  	
  	$options  = " -u " . $currentDb->_user;
  	$options .= " -p".$currentDb->_password;
  	$options .= " --add-locks ";
  	$options .= "--single-transaction -q -e -n --databases ";
  	$options .= $currentDb->_dbName;
  	
  	ob_start();
  	// Execution de la commande d'exportation
  	$command = self::$Dumper." ".$options;

  	passthru($command);
  	$result = ob_get_contents();
  	ob_end_clean();
  	//echo $result;
  	return $result;
  }
  
  // Permet le rechargement de la base de données :
	public static function reload($sqlString) {
	  // Nécéssite un grant lock tables on balloon.* to 'phpBalloon'@'localhost';
		$tmpFile = tempnam("/tmp","balloonSQL");
		file_put_contents($tmpFile,$sqlString);

		$currentDb = Database::getSingleton();
  	
  	$options  = " -u " . $currentDb->_user;
  	$options .= " -p".$currentDb->_password;
  	$options .= " < " .$tmpFile;
  	
  	$output = array();
  	$status = -1;
  	exec(self::$MySql.$options,$output,$status);
		unlink($tmpFile);

		return $status;
	}

}
?>
